package com.classes;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import com.classes.LogManager;

/**
 * @author KhanhND Last Update : 2014-12-15
 */
public class GenerateMD5Checksum {
	/**
	 * @param args
	 */
	private LogManager logmanager;
	private static String resultCode;
	private String strInDir = "";
	private String strOutDir = "";
	private String inputEXT1 = "";
	private String outputEXT1 = "";
	private String inputEXT2 = "";
	private String outputEXT2 = "";
	private String replace_file;
	int total_file;
	// date formatter
	static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyMMdd");
	// config declaration
	static final String CONFIG_FILE = "/GenerateMD5Checksum.properties";
	static final java.util.Properties appCfg = new java.util.Properties();

	/**
	 * Constructor
	 */
	public GenerateMD5Checksum() {
		// Load the properties value
		try {
			InputStream stream = this.getClass().getResourceAsStream(CONFIG_FILE);
			if (stream != null)
				appCfg.load(stream);
			else
				throw new Exception("Input Stream is null");
		} catch (Exception e) {
			resultCode = "RESULT_CODE:0999";
			System.err.println("Error loading file " + CONFIG_FILE);
			System.err.println(e.getMessage());
			e.printStackTrace();
		}
		strInDir = appCfg.getProperty("input_folder");
		strOutDir = appCfg.getProperty("output_folder");
		inputEXT1 = appCfg.getProperty("input_file_ext1");
		outputEXT1 = appCfg.getProperty("output_file_ext1");
		inputEXT2 = appCfg.getProperty("input_file_ext2");
		outputEXT2 = appCfg.getProperty("output_file_ext1");
		replace_file = appCfg.getProperty("replace_file");
		// Initiate LogManager
		//logmanager = LogManager.getInstance(appCfg.getProperty("log_file"));
		//logmanager.logMsg("Log Start:" + this.getClass().getName());
	}

	/**
	 * Process All file in input folder
	 */
	public void processAllInputFile() {
		ArrayList listFiles = new ArrayList();
		try {
			File f = new File(strInDir);
			if (!f.exists()) {
				resultCode = "RESULT_CODE:0093";
			} else {
				File[] files = f.listFiles();
				for (int i = 0; i < files.length; i++) {
					if (checkValidInput(files[i])) {
						listFiles.add(files[i]);
					}
				}
				System.out.println("Processing Data ------");
				System.out.println("Total valid file: " + listFiles.size());
				total_file = listFiles.size();
				if (total_file == 0) {
					resultCode = "RESULT_CODE:0092";
				} else {
					for (int i = 0; i < total_file; i++) {
						File fileProcess = (File) listFiles.get(i);
						System.out.println("Process file " + (i + 1) + ":" + "[" + fileProcess.getName() + "]");
						processOneFile(fileProcess);
						String correctFilePath = fileProcess.getAbsolutePath();
						correctFilePath = correctFilePath.replace('\\', '/');
						// move file
						if (!strInDir.equalsIgnoreCase(strOutDir)) {
							moveFile(correctFilePath, strOutDir);
						}
					}
					System.out.println("Done! --------");
					if (total_file > 1) {
						resultCode = "RESULT_CODE:0021";
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	/**
	 * Process one data file
	 */
	public void processOneFile(File fileToLoad) throws IOException {
		try {
			String fileName = fileToLoad.getName();
			int ind = fileName.lastIndexOf(inputEXT1);
			if (ind > 0) {
				String newName = fileName.substring(0, ind);

				StringBuffer sb = genMD5String(fileToLoad);
				sb.append(" ");
				sb.append(fileName);

				createOutputFile(newName, sb, outputEXT1);
			}
			// check if extension input 2 not empty
			if (!isEmpty(inputEXT2)) {
				int ind2 = fileName.lastIndexOf(inputEXT2);
				if (ind2 > 0) {
					String newName = fileName.substring(0, ind);

					StringBuffer sb = genMD5String(fileToLoad);
					sb.append(" ");
					sb.append(fileName);

					createOutputFile(newName, sb, outputEXT2);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Function to check valid input file
	 */
	public boolean checkValidInput(File file) {
		boolean res = false;
		try {
			String fileName = file.getName();
			int ind = fileName.lastIndexOf(inputEXT1);
			if (ind > 0) {
				if (inputEXT1.equalsIgnoreCase(fileName.substring(ind))) {
					res = true;
				}
			}
			if (!isEmpty(inputEXT2)) {
				int ind2 = fileName.lastIndexOf(inputEXT2);
				if (ind2 > 0) {
					if (inputEXT2.equalsIgnoreCase(fileName.substring(ind2))) {
						res = true;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}

	/**
	 * Function to move the loaded file to success directory
	 */
	public void moveFile(String file, String destination) {
		File a = new File(file);
		String strTempFolder = destination;
		File DestiFolder = new File(strTempFolder);
		String ext = a.getName().substring(a.getName().indexOf("."));
		String name = a.getName().substring(0, a.getName().indexOf("."));
		if (DestiFolder.exists()) {
			File b = new File(strTempFolder + a.getName());
			int count = 1;
			while (b.exists()) {
				b = new File(strTempFolder + name + "_" + count + ext);
				count++;
			}
			if (b.exists()) {
			}
			boolean i = a.renameTo(b);
			System.out.println("Move Sucessful " + i);
		} else {
			boolean j = DestiFolder.mkdirs();
			System.out.println("Make dir Successful " + j);
			boolean i = a.renameTo(new File(strTempFolder + a.getName()));
			System.out.println("Move Sucessful " + i);
		}
	}

	/**
	 * Function create MD5 String
	 */
	public StringBuffer genMD5String(File file) {
		StringBuffer sb = new StringBuffer();
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			FileInputStream fis = new FileInputStream(file);
			byte[] dataBytes = new byte[1024];
			int nread = 0;
			while ((nread = fis.read(dataBytes)) != -1) {
				md.update(dataBytes, 0, nread);
			}
			;
			byte[] mdbytes = md.digest();
			// convert the byte to hex format method 1
			for (int i = 0; i < mdbytes.length; i++) {
				sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
			}
			fis.close();
		} catch (Exception ex) {
			resultCode = "RESULT_CODE:0091";
			//logmanager.logMsg("-- EXCEPTION: " + ex.getClass() + " " + ex.getMessage());
			ex.printStackTrace();
		}
		return sb;
	}

	/**
	 * Function create new output file
	 */
	public void createOutputFile(String newName, StringBuffer sb, String outputExt) {
		String fileName = strOutDir + newName + outputExt;
		File fnew = new File(fileName);
		if ("false".equalsIgnoreCase(replace_file) && fnew.exists()) {
			resultCode = "RESULT_CODE:0090";
		} else {
			try {
				if (total_file == 1) {
					if (fnew.exists()) {
						resultCode = "RESULT_CODE:0001";
					} else {
						resultCode = "RESULT_CODE:0000";
					}
				}
				FileWriter f2 = new FileWriter(fnew, false);
				f2.write(sb.toString());
				f2.close();
			} catch (IOException e) {
				//logmanager.logMsg("-- EXCEPTION: " + e.getClass() + " " + e.getMessage());
				e.printStackTrace();
			}
		}
	}

	/**
	 * Check a string empty or not
	 */
	public boolean isEmpty(String input) {
		if (input == null)
			return true;
		if ("".equals(input.trim()))
			return true;
		return false;
	}

	public static void main(String[] args) {
		GenerateMD5Checksum g = new GenerateMD5Checksum();
		g.processAllInputFile();
		System.out.println(resultCode);
	}
}
